#include "Objects.h"

vec shading(const obj* scenes, const Ray& ray, const int& rayDepth, bool isfst)
{
	if (rayDepth <= 0) return vec(1, 1, 1);

	hitInfo hi(defaultMat);
	bool isHit = scenes->hit(hi, ray);
	if (isHit) {
		if (hi.himat->type == materialType::FLT)
		{
			return hi.himat->color->value(vec2(0, 0), hi, ray);
		}
		else if (hi.himat->type == materialType::EMT)
		{
			scatterInfo si = hi.himat->scatter(hi, ray);
			return si.mult;
		}
		else 
		{
			scatterInfo si = hi.himat->scatter(hi, ray);
			return shading(scenes, si.outRay, rayDepth - 1, false) * si.mult;
		}
	}
	else {
		//return vec(0.5, 0.5, 0.5);
		float lum = acosf(vec::dotProduct(ray.dir.normalized(), vec(0, 0, 1).normalized())) / PI;
		//lum = (lum > 0.6) ? 0.5 : 1.4;
		//return vec(lum-0.2, lum-0.05, lum);

		float sunMult = 1 - clamp01(acosf(vec::dotProduct(vec(-.15, -1, 1).normalized(), ray.dir.normalized())) / DEG2RAD / 12);
		return (1 - lum) * vec(.55, .65, .9999) + lum * vec(.999, .85, .8) + sunMult * vec(1, .75, .6) * 30;
	}
}

QPixmap rend(World world, int sampleTimes, int rayDepth, QProgressBar* pb)
{
	QPixmap outMap = QPixmap(world.cam.viewWidth, world.cam.viewHeight);
	QPainter p(&outMap);
	int process = 0;
	world.cam.update();
	//srand48(time(NULL));
	srand(time(NULL));

	obj* scenes = new obj_list(world.objlist);

#pragma omp parallel for
	for (int i = 0; i < world.cam.viewWidth * world.cam.viewHeight; i++)
	{
		int x = i % world.cam.viewWidth;
		int y = i / world.cam.viewHeight;
		vec color;
		for (int j = 0; j < sampleTimes; j++)
		{
			Ray cray = world.cam.camRay(x, y);
			hitInfo hi(defaultMat);
			color += shading(scenes, cray, rayDepth);
			process++;
			if (pb != NULL) {
				pb->setValue(100.0f * process / (world.cam.viewWidth * world.cam.viewHeight * sampleTimes));
			}
		}
		color /= sampleTimes;
		p.setPen(vec2color(color));
		p.drawPoint(x, y);
	}
	return outMap;
}

void initDefaultVar()
{
	defaultTex = new pureColor(QObject::tr("Default Texture"),Qt::white);
	defaultMat = new Diffuse(QObject::tr("Default Material"), defaultTex);
	texList.append(defaultTex);
	matList.append(defaultMat);
}